<script lang="ts" setup>
import { ref, onMounted, watch, nextTick } from 'vue'
import { ElTree } from 'element-plus'
import dayjs from 'dayjs'
import { useI18n } from 'vue-i18n'

import MenuDialog from './MenuDialog.vue'
import PermissionDialog from './PermissionDialog.vue'
import ReTitle from '@/components/ReTitle/index.vue'
import { Message } from '@/utils/message'
import { Confirm } from '@/utils/messageBox'

import { rules } from './index'
import {
  _queryMenus,
  _deleteMenu,
  _queryCanOperationByMenuId,
  _bindMenuCanOperation,
  _updateMenu,
  _queryMenuDetail,
  _queryMenuPermissions,
  _deletePermission
} from '@/api/auth'
import { MenuItem, OperationItem, PermissionResponse } from '@/api/types'
interface Tree {
  [key: string]: any
}

const { t } = useI18n()
const menuTree = ref([])
const props = {
  value: 'id',
  children: 'children'
}
const filterKeyword = ref('')
const highlightedNode = ref<MenuItem>()
const treeRef = ref<InstanceType<typeof ElTree>>()
const menuDialogRef = ref()
const formRef = ref()

watch(
  () => highlightedNode.value?.id,
  value => {
    value && queryOperations()
    value && queryPermissions()
  }
)

onMounted(async () => {
  await search()
  queryOperations()
})

const onQueryChanged = (query: string) => {
  treeRef.value!.filter(query)
}
const filterMethod = (value: string, data: Tree) => {
  if (!value) return true
  return data.zhName?.includes(value)
}

const expandedKeys = ref([])
const search = (): Promise<void> => {
  return new Promise((resolve, reject) => {
    _queryMenus({})
      .then(res => {
        expandedKeys.value = []
        menuTree.value = filterMenu(res.data)
        // 展开所有第一级节点
        // treeRef.value.setExpandedKeys(expandedKeys)

        if (menuTree.value.length > 0 && !highlightedNode.value) {
          highlightedNode.value = { ...menuTree.value[0] }
          nextTick(() => {
            treeRef.value!.setCurrentKey(highlightedNode.value.id)
          })
        }
        resolve()
      })
      .catch(err => {
        Message.error(err.message)
        reject()
      })
  })
}

const cancel = () => {
  formRef.value.clearValidate()
  getMenuDetail()
}

const getMenuDetail = () => {
  _queryMenuDetail(highlightedNode.value.id)
    .then(res => {
      highlightedNode.value = res.data
    })
    .catch(err => {
      Message.error(err.message)
    })
}

/**
 * @description 更新菜单
 * @returns Promise
 */
const updateMenu = (): Promise<void> => {
  return new Promise((resolve, reject) => {
    formRef.value.validate((valid: boolean) => {
      if (valid) {
        _updateMenu(highlightedNode.value)
          .then(res => {
            Message.success(res.message)
            search()
            resolve()
          })
          .catch(err => {
            reject(err)
            Message.error(err.message)
          })
      } else {
        reject()
      }
    })
  })
}

/**
 * 过滤菜单列表并构建树形结构
 * @param menuList 菜单项列表
 * @returns 返回构建好的树形结构菜单
 */
const filterMenu = (menuList: MenuItem[]): MenuItem[] => {
  // 创建一个 map 用于快速查找菜单项
  const menuMap: { [key: number]: MenuItem } = {}

  // 将所有菜单项放入 map 中
  menuList.forEach(item => {
    expandedKeys.value.push(item.id)
    menuMap[item.id] = { ...item, children: [] }
  })

  // 构建树结构
  const tree: MenuItem[] = []
  menuList.forEach(item => {
    if (item.parentId === null) {
      tree.push(menuMap[item.id])
    } else {
      if (menuMap[item.parentId]) {
        menuMap[item.parentId].children!.push(menuMap[item.id])
      }
    }
  })

  return tree
}

const handleNodeClick = (data: any) => {
  highlightedNode.value = { ...data }
}

/**
 * 新增菜单弹窗
 * @param type 0：新增同级菜单，1：新增子菜单
 */
const handleAddMenu = (type: number) => {
  menuDialogRef.value.show(highlightedNode.value, type)
}

const handleDeleteMenu = () => {
  Confirm(`确定删除菜单： ${highlightedNode.value.zhName} ？`).then(() => {
    _deleteMenu(highlightedNode.value.id)
      .then(res => {
        highlightedNode.value = null
        Message.success(res.message)
        search()
      })
      .catch(err => {
        Message.error(err.message)
      })
  })
}

// 绑定操作
const bindOperationCodes = ref<string[]>([])
const operationList = ref<OperationItem[]>([])
const bindOperations = ref<OperationItem[]>([])

const queryOperations = () => {
  // TODO 查询操作列表
  _queryCanOperationByMenuId({ menuId: highlightedNode.value?.id })
    .then(res => {
      operationList.value = res.data.operationList
      bindOperationCodes.value = res.data.bindOperationCodes
      bindOperations.value = operationList.value.filter(item =>
        bindOperationCodes.value.includes(item.code)
      )
    })
    .catch(err => {
      Message.error(err.message)
    })
}

const filterOptions = (query: string, item: Record<string, any>) =>
  item.name.includes(query) || item.code.includes(query)

/**
 * @description 绑定操作
 * @returns Promise
 */
const updateMenuOperations = (): Promise<void> => {
  console.log(bindOperationCodes.value)

  const params = {
    menuId: highlightedNode.value.id,
    operationCodes: bindOperationCodes.value
  }
  return new Promise((resolve, reject) => {
    _bindMenuCanOperation(params)
      .then(res => {
        Message.success(res.message)
        queryOperations()
        resolve()
      })
      .catch(err => {
        reject(err)
        Message.error(err.message)
      })
  })
}

/** 接口权限操作 */
const permissions = ref([])
const keyword = ref('')
const permissionDialogRef = ref()
const queryPermissions = () => {
  _queryMenuPermissions({
    menuId: highlightedNode.value.id,
    keyword: keyword.value
  }).then(res => {
    permissions.value = res.data
  })
}
const handlePermission = (data?) => {
  permissionDialogRef.value.show(data)
}

const deletePermission = (data: PermissionResponse) => {
  Confirm(`确定删除权限： ${data.name} ？`).then(() => {
    _deletePermission(data.id)
      .then(res => {
        Message.success(res.message)
        queryPermissions()
      })
      .catch(err => {
        Message.error(err.message)
      })
  })
}
</script>

<template>
  <div class="menu-container">
    <div class="menu-tree p-[20px]">
      <el-input
        v-model="filterKeyword"
        class="mb-[20px]"
        placeholder="输入关键字"
        @input="onQueryChanged"
      />
      <el-scrollbar max-height="calc(100% - 55px)">
        <el-tree
          ref="treeRef"
          style="max-width: 600px"
          :data="menuTree"
          node-key="id"
          :props="props"
          highlight-current
          :default-expanded-keys="expandedKeys"
          :current-node-key="highlightedNode?.id"
          :expand-on-click-node="false"
          :filter-node-method="filterMethod"
          @node-click="handleNodeClick"
        >
          <template #default="{ data }">
            <span :class="{ highlight: data.id === highlightedNode?.id }">{{
              data.zhName
            }}</span>
          </template>
        </el-tree>
      </el-scrollbar>
    </div>

    <div class="menu-context p-[20px]">
      <div class="mb-[20px]">
        <el-button type="primary" @click="handleAddMenu(0)">
          {{ t('button.addSiblingMenuText') }}
        </el-button>
        <el-button type="primary" @click="handleAddMenu(1)">
          {{ t('button.addSubmenuText') }}
        </el-button>
        <el-button type="danger" @click="handleDeleteMenu">{{
          t('button.deleteText')
        }}</el-button>
      </div>

      <el-scrollbar v-if="highlightedNode?.id" max-height="calc(100% - 55px)">
        <ReTitle
          title="基础信息"
          canOperate
          :submit="updateMenu"
          @cancel="cancel"
        >
          <template #default="{ status }">
            <el-form
              ref="formRef"
              :model="highlightedNode"
              :rules="rules"
              label-width="100px"
              label-position="right"
            >
              <el-row :gutter="20">
                <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
                  <el-form-item label="菜单名称：" prop="zhName">
                    <el-input v-if="status" v-model="highlightedNode.zhName" />
                    <span v-else>{{ highlightedNode.zhName }}</span>
                  </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
                  <el-form-item label="唯一标识：" prop="name">
                    <el-input v-if="status" v-model="highlightedNode.name" />
                    <span v-else>{{ highlightedNode.name }}</span>
                  </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
                  <el-form-item label="路径：" prop="path">
                    <el-input v-if="status" v-model="highlightedNode.path" />
                    <span v-else>{{ highlightedNode.path || '-' }}</span>
                  </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
                  <el-form-item label="图标：" prop="icon">
                    <el-input v-if="status" v-model="highlightedNode.icon" />
                    <span v-else>{{ highlightedNode.icon || '-' }}</span>
                  </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
                  <el-form-item label="组件：" prop="component">
                    <el-input
                      v-if="status"
                      v-model="highlightedNode.component"
                    />
                    <span v-else>{{ highlightedNode.component || '-' }}</span>
                  </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
                  <el-form-item label="描述：">
                    <el-input
                      v-if="status"
                      v-model="highlightedNode.description"
                      type="textarea"
                      :rows="2"
                    />
                    <span v-else>{{ highlightedNode.description || '-' }}</span>
                  </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
                  <el-form-item label="创建时间：">
                    {{
                      dayjs(highlightedNode.createTime).format(
                        'YYYY-MM-DD HH:mm:ss'
                      )
                    }}
                  </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
                  <el-form-item label="更新时间：">
                    {{
                      dayjs(highlightedNode.updateTime).format(
                        'YYYY-MM-DD HH:mm:ss'
                      )
                    }}
                  </el-form-item>
                </el-col>
              </el-row>
            </el-form>
          </template>
        </ReTitle>

        <ReTitle
          title="操作信息"
          can-operate
          :submit="updateMenuOperations"
          @cancel="queryOperations"
        >
          <template #default="{ status }">
            <el-transfer
              v-if="status"
              v-model="bindOperationCodes"
              filterable
              :filter-method="filterOptions"
              :titles="['未绑定操作', '已绑定操作']"
              :props="{
                key: 'code',
                label: 'name'
              }"
              filter-placeholder="筛选操作"
              :data="operationList"
            >
              <template #default="{ option }">
                <div class="flex justify-between">
                  <span>{{ option.name }}</span>
                  <span>{{ option.code }}</span>
                </div>
              </template>
            </el-transfer>

            <el-table v-else :data="bindOperations">
              <el-table-column label="序号" type="index" width="100" />
              <el-table-column label="操作编码" prop="code" />
              <el-table-column label="操作名称" prop="name" />
            </el-table>
          </template>
        </ReTitle>

        <ReTitle title="接口权限">
          <template #default>
            <div class="mb-2">
              <el-input
                v-model="keyword"
                style="width: 240px"
                placeholder="请输入接口名称"
              />
              <el-button
                type="primary"
                class="ml-2"
                @click="queryPermissions"
                >{{ t('button.queryText') }}</el-button
              >
              <el-button
                @click="
                  () => {
                    keyword = ''
                    queryPermissions()
                  }
                "
                >{{ t('button.resetText') }}</el-button
              >
              <el-button type="primary" @click="handlePermission()">
                {{ t('button.addText') }}
              </el-button>
            </div>
            <el-table :data="permissions" style="width: 100%">
              <el-table-column label="序号" type="index" width="100" />
              <el-table-column label="接口名称" prop="name" />
              <el-table-column label="接口地址" prop="permission" />
              <el-table-column label="类型" prop="type" />
              <el-table-column label="接口地址" prop="description" />
              <el-table-column label="操作" width="140">
                <template #default="{ row }">
                  <el-button type="primary" link @click="handlePermission(row)">
                    {{ t('button.editText') }}
                  </el-button>
                  <el-button type="danger" link @click="deletePermission(row)">
                    {{ t('button.deleteText') }}
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
          </template>
        </ReTitle>
      </el-scrollbar>
      <template v-else>
        <el-empty description="请选择菜单项" />
      </template>
    </div>

    <MenuDialog ref="menuDialogRef" @afterSuccess="search" />
    <PermissionDialog
      ref="permissionDialogRef"
      :menuId="highlightedNode?.id"
      @afterSuccess="queryPermissions"
    />
  </div>
</template>

<style lang="scss" scoped>
.menu-container {
  display: flex;
}

:deep(.menu-tree) {
  flex-shrink: 0;
  width: 360px;
  border-right: 1px solid var(--easy-border-color);

  .el-tree-node__content {
    height: 32px;
    font-size: 15px;
    line-height: 32px;
  }
}

:deep(.menu-context) {
  flex: 1;
}

.highlight {
  color: var(--el-color-primary); /* 你可以根据需要调整高亮颜色 */
}

:deep(.el-transfer-panel) {
  width: 300px;

  .el-transfer-panel__item {
    width: calc(100% - 40px);
  }

  .el-transfer-panel__body {
    max-height: 500px;
  }
}
</style>
